import request from 'supertest';
import { Application } from '@/app';
import { User, IUserDocument } from '@/models';
import { JwtUtil } from '@/utils/jwt';
import { PasswordUtil } from '@/utils/password';

/**
 * 测试工具类
 */
export class TestUtils {
  private static app = new Application();
  
  /**
   * 获取测试应用实例
   */
  static getApp() {
    return this.app.getApp();
  }

  /**
   * 获取 SuperTest 实例
   */
  static getRequest() {
    return request(this.getApp().callback());
  }

  /**
   * 创建测试用户
   */
  static async createTestUser(userData: Partial<IUserDocument> = {}): Promise<IUserDocument> {
    const defaultUser = {
      username: `testuser_${Date.now()}`,
      email: `test_${Date.now()}@example.com`,
      password: 'TestPassword123!',
      firstName: 'Test',
      lastName: 'User',
      role: 'user' as const,
      status: 'active' as const,
      emailVerified: true,
      ...userData,
    };

    const user = new User(defaultUser);
    await user.save();
    return user;
  }

  /**
   * 创建管理员用户
   */
  static async createAdminUser(userData: Partial<IUserDocument> = {}): Promise<IUserDocument> {
    return this.createTestUser({
      role: 'admin',
      ...userData,
    });
  }

  /**
   * 生成用户认证令牌
   */
  static generateAuthToken(user: IUserDocument): string {
    return JwtUtil.generateToken({
      id: user.id,
      email: user.email,
      role: user.role,
    });
  }

  /**
   * 获取认证头
   */
  static getAuthHeaders(token: string): Record<string, string> {
    return {
      Authorization: `Bearer ${token}`,
    };
  }

  /**
   * 创建并认证用户
   */
  static async createAuthenticatedUser(userData: Partial<IUserDocument> = {}): Promise<{
    user: IUserDocument;
    token: string;
    headers: Record<string, string>;
  }> {
    const user = await this.createTestUser(userData);
    const token = this.generateAuthToken(user);
    const headers = this.getAuthHeaders(token);

    return { user, token, headers };
  }

  /**
   * 创建并认证管理员
   */
  static async createAuthenticatedAdmin(userData: Partial<IUserDocument> = {}): Promise<{
    user: IUserDocument;
    token: string;
    headers: Record<string, string>;
  }> {
    const user = await this.createAdminUser(userData);
    const token = this.generateAuthToken(user);
    const headers = this.getAuthHeaders(token);

    return { user, token, headers };
  }

  /**
   * 等待指定时间
   */
  static async delay(ms: number): Promise<void> {
    return new Promise(resolve => setTimeout(resolve, ms));
  }

  /**
   * 生成随机字符串
   */
  static generateRandomString(length: number = 10): string {
    const charset = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789';
    let result = '';
    
    for (let i = 0; i < length; i++) {
      const randomIndex = Math.floor(Math.random() * charset.length);
      result += charset[randomIndex];
    }
    
    return result;
  }

  /**
   * 生成随机邮箱
   */
  static generateRandomEmail(): string {
    return `test_${this.generateRandomString(8)}@example.com`;
  }

  /**
   * 验证响应结构
   */
  static validateApiResponse(response: any, expectedStatus: number = 200): void {
    expect(response.status).toBe(expectedStatus);
    expect(response.body).toHaveProperty('success');
    expect(response.body).toHaveProperty('code');
    expect(response.body).toHaveProperty('message');
    expect(response.body).toHaveProperty('timestamp');
  }

  /**
   * 验证成功响应
   */
  static validateSuccessResponse(response: any, expectedStatus: number = 200): void {
    this.validateApiResponse(response, expectedStatus);
    expect(response.body.success).toBe(true);
    expect(response.body.code).toBe(expectedStatus);
  }

  /**
   * 验证错误响应
   */
  static validateErrorResponse(response: any, expectedStatus: number): void {
    this.validateApiResponse(response, expectedStatus);
    expect(response.body.success).toBe(false);
    expect(response.body.code).toBe(expectedStatus);
  }

  /**
   * 验证分页响应
   */
  static validatePaginatedResponse(response: any, expectedStatus: number = 200): void {
    this.validateSuccessResponse(response, expectedStatus);
    expect(response.body).toHaveProperty('data');
    expect(response.body).toHaveProperty('pagination');
    expect(response.body.pagination).toHaveProperty('page');
    expect(response.body.pagination).toHaveProperty('limit');
    expect(response.body.pagination).toHaveProperty('total');
    expect(response.body.pagination).toHaveProperty('totalPages');
  }

  /**
   * 验证用户对象
   */
  static validateUserObject(user: any): void {
    expect(user).toHaveProperty('id');
    expect(user).toHaveProperty('username');
    expect(user).toHaveProperty('email');
    expect(user).toHaveProperty('firstName');
    expect(user).toHaveProperty('lastName');
    expect(user).toHaveProperty('role');
    expect(user).toHaveProperty('status');
    expect(user).toHaveProperty('createdAt');
    expect(user).toHaveProperty('updatedAt');
    
    // 确保敏感信息不被返回
    expect(user).not.toHaveProperty('password');
    expect(user).not.toHaveProperty('passwordResetToken');
    expect(user).not.toHaveProperty('emailVerificationToken');
  }

  /**
   * 清理测试数据
   */
  static async cleanup(): Promise<void> {
    // 在这里添加清理逻辑，比如删除测试文件、清空缓存等
  }
}

/**
 * 测试数据工厂
 */
export class TestDataFactory {
  /**
   * 创建用户测试数据
   */
  static createUserData(overrides: Partial<any> = {}): any {
    return {
      username: `testuser_${Date.now()}`,
      email: TestUtils.generateRandomEmail(),
      password: 'TestPassword123!',
      confirmPassword: 'TestPassword123!',
      firstName: 'Test',
      lastName: 'User',
      phone: '13800138000',
      ...overrides,
    };
  }

  /**
   * 创建登录数据
   */
  static createLoginData(overrides: Partial<any> = {}): any {
    return {
      email: TestUtils.generateRandomEmail(),
      password: 'TestPassword123!',
      rememberMe: false,
      ...overrides,
    };
  }
}

export default TestUtils;